package com.project.srtp.secure.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.project.srtp.secure.dao.entity.DecryptionSenderKeyDO;
import com.project.srtp.secure.dao.mapper.DecryptionSenderKeyMapper;
import com.project.srtp.secure.dto.req.HasDecryptionSenderKeyReqDTO;
import com.project.srtp.secure.dto.req.StoreDecryptionSenderKeyReqDTO;
import com.project.srtp.secure.dto.req.getDecryptionSenderKeyReqDTO;
import com.project.srtp.secure.dto.resp.GetDecryptionSenderKeyRespDTO;
import com.project.srtp.secure.dto.resp.GetSessionIdRespDTO;
import com.project.srtp.secure.service.DecryptionSenderKeyService;
import com.project.srtp.secure.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 曹行阳
 * @version 0.1
 * @date 2025/6/16 23:39
 */
@Service
@RequiredArgsConstructor
public class DecryptionSenderKeyServiceImpl extends ServiceImpl<DecryptionSenderKeyMapper, DecryptionSenderKeyDO> implements DecryptionSenderKeyService {
    private final UserService userService;

    @Override
    public Boolean hasDecryptionSenderKey(HasDecryptionSenderKeyReqDTO request) {
        String forUserId = request.getForUserId();
        String ofUserId = request.getOfUserId();
        String sessionId = request.getSessionId();
        LambdaQueryWrapper<DecryptionSenderKeyDO> queryWrapper = Wrappers.lambdaQuery(DecryptionSenderKeyDO.class)
                .eq(DecryptionSenderKeyDO::getForUserId, forUserId)
                .eq(DecryptionSenderKeyDO::getOfUserId, ofUserId)
                .eq(DecryptionSenderKeyDO::getSessionId, sessionId);
        return baseMapper.selectCount(queryWrapper) > 0;
    }

    @Override
    public GetDecryptionSenderKeyRespDTO getDecryptionSenderKey(getDecryptionSenderKeyReqDTO request) {
        String forUserId = request.getForUserId();
        String ofUserId = request.getOfUserId();
        LambdaQueryWrapper<DecryptionSenderKeyDO> queryWrapper = Wrappers.lambdaQuery(DecryptionSenderKeyDO.class)
                .eq(DecryptionSenderKeyDO::getForUserId, forUserId)
                .eq(DecryptionSenderKeyDO::getOfUserId, ofUserId);
        DecryptionSenderKeyDO decryptionSenderKeyDO = baseMapper.selectOne(queryWrapper);
        return GetDecryptionSenderKeyRespDTO.builder()
                .senderKey(decryptionSenderKeyDO.getSenderKey())
                .identityKeyId(decryptionSenderKeyDO.getIdentityKeyId())
                .sessionId(decryptionSenderKeyDO.getSessionId())
                .build();
    }

    @Override
    public void storeDecryptionSenderKey(StoreDecryptionSenderKeyReqDTO request) {
        DecryptionSenderKeyDO decryptionSenderKeyDO = DecryptionSenderKeyDO.builder()
                .forUserId(request.getForUserId())
                .ofUserId(request.getOfUserId())
                .sessionId(request.getSessionId())
                .senderKey(request.getSenderKey())
                .identityKeyId(request.getIdentityKeyId())
                .partyId(request.getSessionId().substring(0, 32))
                .build();
        LambdaQueryWrapper<DecryptionSenderKeyDO> queryWrapper = Wrappers.lambdaQuery(DecryptionSenderKeyDO.class);
        // 根据 one-time ID 是否为空，判断使用哪一组主键条件
        if (StringUtils.hasText(decryptionSenderKeyDO.getForOneTimeId()) && StringUtils.hasText(decryptionSenderKeyDO.getForOneTimeId())) {
            queryWrapper.eq(DecryptionSenderKeyDO::getOfOneTimeId, decryptionSenderKeyDO.getForOneTimeId())
                    .eq(DecryptionSenderKeyDO::getForOneTimeId, decryptionSenderKeyDO.getForOneTimeId())
                    .eq(DecryptionSenderKeyDO::getSessionId, request.getSessionId());
        } else {
            queryWrapper.eq(DecryptionSenderKeyDO::getOfUserId, request.getOfUserId())
                    .eq(DecryptionSenderKeyDO::getForUserId, request.getForUserId())
                    .eq(DecryptionSenderKeyDO::getSessionId, request.getSessionId());
        }

        // 尝试更新
        DecryptionSenderKeyDO existing = baseMapper.selectOne(queryWrapper);
        if (existing != null) {
            // 已存在则更新（基于 ID）
            boolean success = this.updateById(decryptionSenderKeyDO);
            if (!success) {
                throw new RuntimeException("更新解密会话密钥失败");
            }
        } else {
            // 不存在则插入
            boolean success = this.save(decryptionSenderKeyDO);
            if (!success) {
                throw new RuntimeException("插入解密会话密钥失败");
            }
        }
        int updated = baseMapper.update(decryptionSenderKeyDO, queryWrapper);

        // 如果没有更新到任何记录，则插入
        if (updated == 0) {
            baseMapper.insert(decryptionSenderKeyDO);
        }
    }

    @Override
    public List<GetSessionIdRespDTO> getAllSessionId(String userId) {
        LambdaQueryWrapper<DecryptionSenderKeyDO> queryWrapper = Wrappers.lambdaQuery(DecryptionSenderKeyDO.class)
                .eq(DecryptionSenderKeyDO::getOfUserId, userId);
        List<DecryptionSenderKeyDO> decryptionSenderKeyDOList = baseMapper.selectList(queryWrapper);
        List<GetSessionIdRespDTO> resp = new ArrayList<>();
        for (DecryptionSenderKeyDO decryptionSenderKeyDO : decryptionSenderKeyDOList) {
            String username = userService.getUserNameByUserId(decryptionSenderKeyDO.getForUserId());
            GetSessionIdRespDTO getSessionIdRespDTO = new GetSessionIdRespDTO(username, decryptionSenderKeyDO.getSessionId());
            resp.add(getSessionIdRespDTO);
        }

        return resp;
    }
}
